/*
 * Copyright 2011 LMAX Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lmax.disruptor;


/**
 * {@link SequenceBarrier} handed out for gating {@link EventProcessor}s on a cursor sequence and optional dependent {@link EventProcessor}(s),
 * using the given WaitStrategy.
 *
 *
 * 简单总结一下：ProcessingSequenceBarrier作用
 * （1）waitFor 获取下一个可用的消费序号
 * （2）getCursor  获取依赖对象（生产者 或者 消费者序号）序号的最小序号
 */
final class ProcessingSequenceBarrier implements SequenceBarrier {
    private final WaitStrategy waitStrategy; //等待策略waitStrategy

    private final Sequence dependentSequence;   // 依赖序号  不能超过  ，
    private volatile boolean alerted = false; // 警报
    private final Sequence cursorSequence;  //生产者位cursorSequence
    private final Sequencer sequencer; // 生产者Sequencer

    ProcessingSequenceBarrier(
            final Sequencer sequencer, // 生产者实列引用
            final WaitStrategy waitStrategy, // 等待策略
            final Sequence cursorSequence, // 生产者 当前生产的序号 序号
            final Sequence[] dependentSequences // 依赖的序号   注意：第一次的时候，dependentSequences是一个空数组
    ) {
        this.sequencer = sequencer; // 生产者实列
        this.waitStrategy = waitStrategy; // 等待策略waitStrategy
        // cursorSequence其实持有的是AbstractSequencer的成员变量cursor实例的引用
        this.cursorSequence = cursorSequence; // 当前生产者序号
        // 如果消费者前面依赖的其他消费者链长度为0，其实就是只有一个消费者的情况下，
        // 那么dependentSequence其实就是生产者的cursor游标
        if (0 == dependentSequences.length) {
            // dependentSequences 为0 那么依赖 生产者序号
            dependentSequence = cursorSequence;
        }
        // 如果消费者前面还有被依赖的消费者，那么dependentSequence就是前面消费者的sequence
        // 如果是指定执行顺序链的会执行到这里，
        // 比如 disruptor.after(eventHandler1).handleEventsWith(eventHandler2);
        else {// FixedSequenceGroup 包装了Sequence[] dependentSequences数组，然后提供了获取这个数组中最小序号的方法
            dependentSequence = new FixedSequenceGroup(dependentSequences);
        }
    }

    @Override
    public long waitFor(final long sequence)
            throws AlertException, InterruptedException, TimeoutException {
        checkAlert();
        // （1）委托给了waitStrategy的实现类
        long availableSequence = waitStrategy.waitFor(sequence, cursorSequence, dependentSequence, this);

        if (availableSequence < sequence) {
            return availableSequence;
        }
        // 这个主要是针对多生产者的情形   单生产者返回availableSequence
        return sequencer.getHighestPublishedSequence(sequence, availableSequence);
    }

    @Override
    public long getCursor() {
        return dependentSequence.get();
    }

    @Override
    public boolean isAlerted() {
        return alerted;
    }

    @Override
    public void alert() {
        alerted = true;
        waitStrategy.signalAllWhenBlocking();
    }

    @Override
    public void clearAlert() {
        alerted = false;
    }

    @Override
    public void checkAlert() throws AlertException {
        if (alerted) {
            throw AlertException.INSTANCE;
        }
    }
}